<?php
/**
 * Created by PhpStorm.
 * User: shenzhe
 */
namespace http;

use think\facade\Log;

class Curl {

    protected $connectTimeOut = 5;
    protected $readTimeOut = 10;
    protected $doLog = true;
    protected $sslCert = null;
    protected $sslKey = null;

    public function __construct() {

    }

    /**
     * @param $connectTimeOut
     * @return $this
     */
    public function setConnectTimeOut($connectTimeOut)
    {
        $this->connectTimeOut = $connectTimeOut;
        return $this;
    }

    /**
     * @return int
     */
    public function getConnectTimeOut()
    {
        return $this->connectTimeOut;
    }

    /**
     * @param $readTimeOut
     * @return $this
     */
    public function setReadTimeOut($readTimeOut)
    {
        $this->readTimeOut = $readTimeOut;
        return $this;
    }

    /**
     * @return int
     */
    public function getReadTimeOut()
    {
        return $this->readTimeOut;
    }

    /**
     * @param boolean $doLog
     */
    public function setDoLog($doLog)
    {
        $this->doLog = (bool)$doLog;
    }

    /**
     * @return null
     */
    public function getSslCert()
    {
        return $this->sslCert;
    }

    /**
     * @param null $sslCert
     */
    public function setSslCert($sslCert)
    {
        $this->sslCert = $sslCert;
    }

    /**
     * @return null
     */
    public function getSslKey()
    {
        return $this->sslKey;
    }

    /**
     * @param null $sslKey
     */
    public function setSslKey($sslKey)
    {
        $this->sslKey = $sslKey;
    }

    public function request($url,$params=array(),$requestMethod='GET',$jsonDecode=true,$headers=array()) {
        $return = array(
            'httpcode' => 200,
            'data' => array(),
        );
        try {
            $now = time();
            $ci = curl_init();
            curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ci, CURLOPT_USERAGENT, 'PHP');
            curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connectTimeOut);
            curl_setopt($ci, CURLOPT_TIMEOUT, $this->readTimeOut);
            curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ci, CURLOPT_ENCODING, '');
            curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ci, CURLOPT_HEADER, true);

            $requestMethod = strtoupper($requestMethod);
            switch ($requestMethod) {
                case 'POST':
                    curl_setopt($ci, CURLOPT_POST, true);
                    if ($params) {
                        curl_setopt($ci, CURLOPT_POSTFIELDS, $params);
                    }
                    else {
                        curl_setopt($ci, CURLOPT_POSTFIELDS, '');
                    }
                    break;
                case 'DELETE':
                    curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
                    if ($params) {
                        $url = "{$url}?{$params}";
                    }
                    break;
                case 'GET':
                    if($params) {
                        $sep = false === strpos($url,'?') ? '?' : '&';
                        $url .= $sep . http_build_query($params);
                    }
                    break;
                case 'PUT':
                    if($params) {
                        curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'PUT');
                        curl_setopt($ci, CURLOPT_POSTFIELDS, $params);
                    }
                    break;
            }
            //$headers[] = "APIWWW: " . $_SERVER['REMOTE_ADDR'];
            curl_setopt($ci, CURLOPT_URL, $url );
            curl_setopt($ci, CURLOPT_HTTPHEADER, $headers );
            curl_setopt($ci, CURLINFO_HEADER_OUT, true );
            if($this->sslCert){
                curl_setopt($ci,CURLOPT_SSLCERTTYPE,'PEM');
                curl_setopt($ci,CURLOPT_SSLCERT,$this->sslCert);
            }
            if($this->sslKey){
                curl_setopt($ci,CURLOPT_SSLKEYTYPE,'PEM');
                curl_setopt($ci,CURLOPT_SSLKEY,$this->sslKey);
            }

            if($this->doLog) {
                $statistics_start_time = microtime(true);
            }

            $response = curl_exec($ci);
            /*list($responseHeader, $responseBody) = explode("\r\n\r\n", $response, 2);*/
            $headerSize = curl_getinfo($ci, CURLINFO_HEADER_SIZE);
            $responseHeader = substr($response, 0, $headerSize);
            $responseBody = substr($response, $headerSize);
            $httpCode = curl_getinfo($ci, CURLINFO_HTTP_CODE);

            if($this->doLog) {
                Log::info("http.request=".json_encode(array(
                    'url'=>$url,
                    'params'=>$params,
                    'method'=>$requestMethod,
                    'httpCode'=>$httpCode,
                    'requestTime'=>$now,
                    'elapsedTime'=>microtime(true)-$statistics_start_time,
                    'requestHeader'=>$headers,
                    'responseHeader'=>$responseHeader,
                    'error'=>curl_error($ci),
                    'responseBody'=>$responseBody,
                ),JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));
            }
            $return = array(
                'httpcode' => $httpCode,
                'data' =>  ($jsonDecode ? @json_decode($responseBody,true) : $responseBody),
            );

            curl_close ($ci);
        }
        catch (\Exception $e) {
            Log::info("http.request.error={$e->getMessage()}");
        }
        return $return;
    }

}